<template>
  <div>
    <div
      class="titles"
      v-if="title"
    >
      {{ title }}
    </div>
    <el-table
      :size="size"
      ref="tableRefs"
      border
      :data="pagesTableDate"
      style="width: 100%"
      :height="height"
      @select="select"
      @select-all="selectAll"
      class="main-table"
      v-loading="loading"
    >
      <template v-for="(ele, i) in columns">
        <!-- 这是表格第一列的checkbox 和序号的 -->
        <el-table-column
          :key="i + '-0'"
          :align="ele.align || 'center'"
          :type="ele.type"
          :width="ele.width"
          v-if="ele.type"
          :label="ele.title"
          :fixed="ele.fixed || false"
          v-bind="ele.attrs"
        />
        <!-- 这是普通的 -->
        <el-table-column
          :key="i + '-1'"
          :prop="ele.dataIndex"
          :label="ele.title"
          :min-width="ele.width"
          v-if="!ele.render?.length && !ele.type"
          :align="ele.align || 'center'"
          :fixed="ele.fixed || false"
          :show-overflow-tooltip="ele.showOverflowTooltip||showOverflowTooltip"
        >
          <template #default="{ row }">
            <section
              class="row_item"
              @click="isShowIpt(row, ele)"
              v-if="ele.edit"
            >
              <!-- <section class="row_item" @click="isShowIpt(row,ele)" v-if="ele.edit"> -->
              <!-- v-show="row[ele.dataIndex+'__isshow']"  -->
              <component
                :is="`el-${ele.edit}`"
                ref="iptRefs"
                v-model="row[ele.dataIndex]"
                :ipt-key="row[ele.dataIndex + '__isKey']"
                size="mini"
                @blur="blur(row, ele)"
                format="YYYY-MM-DD"
                :value-format="ele.format ? ele.format : 'YYYY-MM-DD'"
                style="width: 100%"
                v-on="ele.attrsFun"
                :disabled="typeof ele.disabled === 'function' ? ele.disabled(row) : ele.disabled"
              >
                <div v-if="ele.option">
                  <component
                    v-for="(item, index) in ele.option?.data"
                    :is="`el-${ele.option?.type}`"
                    :key="`${index}-2`"
                    :value="item.value ? item.value : item.bussinessValue"
                    :label="item.label ? item.label : item.showName"
                  />
                </div>
              </component>
              <div v-if="false">
                <!-- <div v-show="!row[ele.dataIndex+'__isshow']"> -->
                {{ ele.option ? ele.option.data?.find((_e) => _e.value == row[ele.dataIndex])?.label || row[ele.dataIndex] : row[ele.dataIndex] }}
                <span class="seizeASeat">.</span>
              </div>
              <div
                class="row_item_prompt"
                :style="`height:${getRules(ele, row).status ? '12px' : '0'}`"
              >
                {{ getRules(ele, row).message }}
              </div>
            </section>
            <div v-else>
              {{ row[ele.dataIndex] }}
            </div>
          </template>
        </el-table-column>
        <!-- 这是写render自定义-->
        <el-table-column
          :key="i + '-2'"
          :prop="ele.dataIndex"
          :label="ele.title"
          :width="ele.width"
          v-if="ele.render?.length && !ele.type"
          :align="ele.align || 'center'"
          :fixed="ele.fixed || false"
          :show-overflow-tooltip="ele.showOverflowTooltip||showOverflowTooltip"
        >
          <template #default="{ row }">
            <div class="components">
              <div
                v-for="(item, ii) in ele.render"
                class="components_item"
                :key="ii"
                v-show="item.isHide ? !item?.isHide(clearSideEffect(row)) : true"
              >
                <component
                  :is="item.isName"
                  :row="row"
                  @click="click(item, row)"
                  :type="item.type"
                  :size="item?.sizi || 'mini'"
                  :icon="item.icon || ''"
                  :diy-attrs="item?.attrs&&item?.attrs(clearSideEffect(row))||{}"
                >
                  {{ typeof item.text === "string" ? item.text : item.text(clearSideEffect(row)) }}
                </component>
              </div>
            </div>
          </template>
        </el-table-column>
      </template>
    </el-table>
    <div
      class="pagination"
      v-if="showPagination"
    >
      <el-pagination
        :disabled="loading"
        background
        layout="total, sizes, prev, pager, next, jumper"
        :page-size="paging.size"
        :total="!pagination?.localPage ? paging.total : forms.data?.length"
        :page-sizes="paging.pageSizes"
        :current-page="paging.current"
        @size-change="sizeChange"
        @current-change="currentChange"
      />
    </div>
  </div>
</template>

<script setup>
/**
   * pagination:{
   * localPage:true, //本地分页
   * }
   *
   */
import { ref, defineProps, defineEmits, reactive, watch, onMounted, computed } from 'vue'
import { v4 as uuidv4 } from 'uuid'
import { MessageBox, Message } from '@/utils/element'
import _ from 'lodash'
const emits = defineEmits(['select', 'select-all', 'example'])
const props = defineProps({
  data: Array,
  columns: Array,
  pagination: {
    type: Object,
    default: () => {
      return {}
    }
  },
  showPagination: {
    type: Boolean,
    default: true
  },
  height: {
    type: String,
    default: null
  },
  border: {
    type: Boolean,
    default: true
  },
  loading: {
    type: Boolean,
    default: false
  },
  title: String,
  size: {
    type: String,
    default: ''
  },
  showOverflowTooltip: {
    type: Boolean,
    default: true
  }
})

const pagingCurrent_1 = () => paging.current = paging.current - 1

const pagesTableDate = computed(() => {
  if (!props.pagination?.localPage) {
    return forms.data
  } else {
    let pageData = forms.data.filter((ele, i) => i >= (paging.current - 1) * paging.size && i < (paging.current - 1) * paging.size + paging.size)
    if (!pageData.length && forms.data.length) {
      // paging.current = paging.current - 1
      pagingCurrent_1()
      pageData = forms.data.filter((ele, i) => i >= (paging.current - 1) * paging.size && i < (paging.current - 1) * paging.size + paging.size)
    }
    return pageData
  }
})

/**
   * 清除副作用
   */
const clearSideEffect = (_r) => {
  let row = { ..._r }
  for (const key in row) {
    delete row[key + '__isshow']
    delete row[key + '__isKey']
    if (!row[key] && row[key] !== 0) row[key] = null
  }
  return row
}
//记录每一个输入框是否校验通过的状态
let recordVerificationStatus = {}
const getRules = (ele, row) => {
  if (!ele.rules) {
    recordVerificationStatus[row[ele.dataIndex + '__isKey']] = false
    return {
      status: false
    }
  } else {
    const _v = ele.rules(clearSideEffect(row))
    recordVerificationStatus[row[ele.dataIndex + '__isKey']] = _v.status
    return _v
  }
}
/**
   * 表格的实例
   */
const tableRefs = ref(null)
/**获取所有input的数组*/
const iptRefs = ref(null)
const isShowIpt = (row, ele) => {
  row[ele.dataIndex + '__isshow'] = true
  new Promise((rej) => {
    let _obj = iptRefs.value.find((item) => {
      let keys = item.$attrs['ipt-key']
      return keys == row[ele.dataIndex + '__isKey']
    })
    rej(_obj)
  }).then((refs) => {
    refs.focus()
  })
}
/**
   * input失焦
   * 每次失焦都清除选中行
   *
   */
const blur = (row, ele) => {
  //失焦不消失
  row[ele.dataIndex + '__isshow'] = false
  tableRefs.value?.clearSelection && tableRefs.value?.clearSelection()
  ele.blur && ele.blur(clearSideEffect(row))
  emits('select-all', [])
  emits('select', [])
}
/**
   * 为了保证input始终可以双向数据绑定 并且组件之间单项数据流的原则
   * 这里做了个深拷贝
   */
const forms = reactive({ data: [] })
/**
   * 这里给每一个项添加一个唯一keyhe唯一控制显示隐藏的方式
   * 为了能找到这个input的实例
   */
watch(
  () => props.data,
  () => {
    recordVerificationStatus = {}
    forms.data = _.cloneDeep(props.data)?.map((ele) => {
      for (const key in ele) {
        ele[key + '__isshow'] = false
        ele[key + '__isKey'] = uuidv4()
      }
      ele['__key__'] = uuidv4()
      return ele
    })
  },
  { deep: true, immediate: true }
)

watch(
  () => forms.data,
  () => {
    if (!forms.data?.length) {
      paging.size = 10
      paging.total = 0
      paging.current = 1
    }
  }
)

/**
   * 获取生成表格的数据
   */
const _get = (authority, msg) => {
  if (!authority) {
    if (Object.values(recordVerificationStatus).includes(true)) {
      Message.error(msg || '请将表格必填项输入完整!')
      return undefined
    }
  }

  return _.cloneDeep(forms.data).map((ele) => clearSideEffect(ele))
}

/**
   * 重新写入表格数据
   */
const _set = (key, obj, callback) => {
  forms.data = forms.data.map((ele) => {
    if (ele.__key__ === key) {
      ele = { ...ele, ...obj }
    }
    return ele
  })
  callback && callback()
}
/**
   * 批量更新*/
const _sets = (data, callback) => {
  forms.data = [...forms.data, ...data]
  //本地分页,触发第二页校验
  const _columns = props.columns.filter((ele) => ele.dataIndex && !ele.render)
  data.forEach(row => _columns.forEach(ele => getRules(ele, row)))
  callback && callback()
}
/**
   * 添加一行的逻辑
   */
const _add = (fun, defaultValue = {}) => {
  let obj = {}
  const _columns = props.columns.filter((ele) => ele.dataIndex && !ele.render)
  _columns.forEach((ele) => {
    if (typeof ele.editValue === 'function') {
      obj[ele.dataIndex] = ele.editValue()
    } else if (ele.editValue && typeof ele.editValue !== 'function') {
      obj[ele.dataIndex] = ele.editValue
    } else {
      obj[ele.dataIndex] = ''
    }
  })
  obj['__key__'] = uuidv4()
  for (const key in obj) {
    obj[key + '__isshow'] = false
    obj[key + '__isKey'] = uuidv4()
  }
  _columns.forEach(item => {
    getRules(item, obj)
  })
  forms.data.push({ ...obj, ...defaultValue })
  fun && fun(obj['__key__'])
}

/**
   * 默认选中的的方法
   * @params selectList 需要选中的唯一值的数组
   * @params key 需要从表格里对应的数据的 key
   */
const defaultselect = (selectList, key) => {
  selectList.forEach((ele) => {
    tableRefs.value.toggleRowSelection(
      forms.data.find((item) => item[key] === ele),
      true
    )
  })
}

/**
   * 删除一行数据的逻辑
   * @key 接受一个对象内带有__key__的数组集合
   * _del 会返回一个promise 成功执行.then  失败.catch
   */
const _del = (key, callback) => {
  if (!key.length) return Message.error('请至少选择一条删除')
  return new Promise((rej, req) => {
    MessageBox({
      title: '提示',
      type: 'error',
      message: '确定删除吗'
    })
      .then(() => {
        forms.data = forms.data.filter((ele) => {
          return !key.includes(ele.__key__)
        })
        callback &&
            callback(
              forms.data
                .filter((ele) => {
                  return key.includes(ele.__key__)
                })
                .map((item) => clearSideEffect(item)),
              forms.data.map((item) => clearSideEffect(item))
            )
        emits('select', [])
        recordVerificationStatus = {}
        Message.success('成功!')

        rej()
      })
      .catch(() => {
        console.log('取消删除')
        req()
      })
  })
}
onMounted(() => {
  emits('example', {
    _get,
    _set,
    _add,
    _del,
    _clear: () => {
      forms.data = []
      recordVerificationStatus = {}
    },
    _sets,
    _tableRefs: tableRefs.value,
    _defaultselect: defaultselect
  })
})

const paging = reactive({
  pageSizes: [10, 20, 30, 40, 50],
  total: 0, //总条数
  current: 1, //当前页
  size: 10 //每页多少条
})
const sizeChange = (_v) => {
  paging.size = _v
  if (props?.pagination?.onChange) props.pagination?.onChange({ pageNum: paging.current, pageSize: paging.size })
}
const currentChange = (_v) => {
  paging.current = _v
  if (props?.pagination?.onChange) props.pagination?.onChange({ pageNum: paging.current, pageSize: paging.size })
}
const click = (item, _row) => item.click && item.click(clearSideEffect(_row))

const select = (_selection, _row) => {
  let selection = _.cloneDeep(_selection)?.map((ele) => {
    for (const key in ele) {
      delete ele[key + '__isshow']
      delete ele[key + '__isKey']
    }
    return ele
  })
  let row = { ..._row }
  for (const key in row) {
    delete row[key + '__isshow']
    delete row[key + '__isKey']
  }
  props.columns.find((ele) => ele.type).click && props.columns.find((ele) => ele.type).click(selection, row)
  emits('select', selection, row)
}
const selectAll = (_selection) => {
  let selection = _.cloneDeep(_selection)?.map((ele) => {
    for (const key in ele) {
      delete ele[key + '__isshow']
      delete ele[key + '__isKey']
    }
    return ele
  })
  emits('select-all', selection)
  props.columns.find((ele) => ele.type).click && props.columns.find((ele) => ele.type).click(selection)
}
watch(
  () => props.pagination,
  () => {
    if (props?.pagination) {
      Object.keys(props.pagination).forEach((ele) => {
        paging[ele] = props.pagination[ele]
      })
    }
  },
  { deep: true }
)
// {
//     title: '证件类型',
//     dataIndex: 'idCheckStatus4',
//     edit: 'select',
// option: {
//   type: 'option',
//   data: [
//     {
//       label: '身份证',
//       value: '身份证111'
//     },
//     {
//       label: '护照',
//       value: '护照666'
//     }
//   ]
// }
//   },
</script>
<style lang="scss">
  .components {
    display: flex;
    justify-content: space-around;
    .components_item {
      margin-right: 5px;
    }
  }
  .titles {
    margin-bottom: 10px;
    margin-left: -10px;
  }
  .row_item {
    width: 100%;
    height: 100%;
    .row_item_prompt {
      color: #f56c6c;
      height: 0;
      margin-top: 3px;
      overflow: hidden;
      font-size: 12px;
      line-height: 12px;
      white-space: nowrap;
      text-overflow: ellipsis;
      transition: 0.2s;
    }
  }
  .seizeASeat {
    color: rgb(0 0 0 / 0%);
  }
</style>
